/* typehints:start */
import { Application } from "../../application";
/* typehints:end */

import { createLogger } from "../utils/logging";
import { ReadWriteProxy } from "../utils/read_write_proxy";
import { BoolSetting, EnumSetting, RangeSetting } from "./setting_type";

const logger = createLogger('setting')

export const enumCategories = {
  general: {
    key: 'general',
    text: '通用'
  },
  userInterface: {
    key: 'userInterface',
    text: '用户界面'
  },
  advanced: {
    key: 'advanced',
    text: '高级'
  }
}

export const uiScales = [
  {
    id: 'super_small',
    text: '最小',
    size: 0.6
  },
  {
    id: 'small',
    text: '较小',
    size: 0.8
  },
  {
    id: 'regular',
    text: '正常',
    size: 1,
  },
  {
    id: 'large',
    text: '较大',
    size: 1.05
  },
  {
    id: 'huge',
    text: '最大',
    size: 1.1
  }
]

export const fontFamily = [
  {
    id: 'GameFont',
    text: '正常',
  },
  {
    id: 'GameFont2',
    text: '鸿雷板书'
  },
  {
    id: 'GameFont3',
    text: '小米字体'
  }
]

export const themes = [
  {
    id: 'light',
    text: '浅色'
  },
  {
    id: 'dark',
    text: '深色'
  },
]

export const allApplicationSettings = [
  new EnumSetting('uiScale', {
    label: '用户界面大小',
    description: '用户界面按比率缩放。',
    options: uiScales.sort((a, b) => a.size - b.size),
    valueGetter: scale => scale.id,
    textGetter: scale => scale.text,
    category: enumCategories.userInterface.key,
    restartRequired: false,
    /**
     * 
     * @param {Application} app 
     * @param {*} id 
     * @returns 
     */
    changeCb: (app, id) => app.checkResize(true)
  }),

  new EnumSetting('fontFamily', {
    label: '用户字体',
    description: '以不同的字体来演绎这个游戏世界',
    options: fontFamily,
    valueGetter: scale => scale.id,
    textGetter: scale => scale.text,
    category: enumCategories.userInterface.key,
    restartRequired: false,
    /**
     * 
     * @param {Application} app 
     * @param {*} id 
     * @returns 
     */
    changeCb: (app, id) => app.changeFontFamily(id)
  }),

  new BoolSetting(
    'soundSwitch',
    '静音',
    '关闭所有的音效音乐',
    enumCategories.general.key,
    /**
     * 
     * @param {Application} app 
     * @param {*} value 
     * @returns 
     */
    (app, value) => {
      app.sound.setSoundSwitch(value);
    }
  ),

  new RangeSetting(
    'soundVolume',
    '音效音量',
    '设置音效的音量',
    enumCategories.general.key,
    /**
     * 
     * @param {Application} app 
     * @param {*} value 
     * @returns 
     */
    (app, value) => app.sound.setSoundVolume(value)
  ),

  new RangeSetting(
    'musicVolume',
    '音乐音量',
    '设置音乐的音量',
    enumCategories.general.key,
    /**
     * 
     * @param {Application} app 
     * @param {*} value 
     * @returns 
     */
    (app, value) => app.sound.setMusicVolume(value)
  ),

  new EnumSetting('theme', {
    label: '界面主题',
    description: '选择界面的主题（深色或浅色）',
    options: themes,
    valueGetter: theme => theme.id,
    textGetter: theme => theme.text,
    category: enumCategories.userInterface.key,
    restartRequired: false,
    /**
     * 
     * @param {Application} app 
     * @param {*} id 
     */
    changeCb: (app, id) => {
      document.documentElement.setAttribute('data-theme', id);
    },
    enabledCb: app => false
  }),

  new BoolSetting(
    'leaveWorldStopGame',
    '暂停游戏',
    '游戏中离开世界页面是否需要暂停游戏',
    enumCategories.advanced.key,
    /**
     * 
     * @param {Application} app 
     * @param {*} value 
     * @returns 
     */
    (app, value) => {
      app.sound.setSoundSwitch(value);
    }
  ),

  new BoolSetting(
    'battleCutSkillDesc',
    '精简技能介绍',
    '在战斗中，将只显示技能标题',
    enumCategories.advanced.key,
    /**
     * 
     * @param {Application} app 
     * @param {*} value 
     * @returns 
     */
    (app, value) => {
    }
  ),

  new BoolSetting(
    'reverseDialogueAndDetail',
    'Npc操作方式',
    '开启后在世界中与Npc对话的操作改为长按，详情改为单击，关闭则反之',
    enumCategories.advanced.key,
    /**
     * 
     * @param {Application} app 
     * @param {*} value 
     * @returns 
     */
    (app, value) => {
    }
  ),

  new BoolSetting(
    'posUnitScrollTop',
    '定位战斗单位',
    '开启后，每回合开始时将会定位至该单位位置',
    enumCategories.advanced.key,
    /**
     * 
     * @param {Application} app 
     * @param {*} value 
     * @returns 
     */
    (app, value) => {
    }
  ),
]

class SettingStorage{
  constructor(){
    this.uiScale = 'regular';
    this.fontFamily = 'GameFont';

    this.soundSwtich = false;
    this.musicVolume = 1.0;
    this.soundVolume = 1.0;

    this.theme = 'light';

    // 离开世界页面是否需要暂停游戏
    this.leaveWorldStopGame = true;
    // 战斗中精简技能介绍
    this.battleCutSkillDesc = false;
    // 翻转npc详情与对话的操作方式
    this.reverseDialogueAndDetail = false;
    // 战斗定位单位
    this.posUnitScrollTop = true;
  }
}

export class Setting extends ReadWriteProxy{
  constructor(app){
    super(app, 'settings')
  }

  getDefaultData(){
    return new SettingStorage;
  }

  getAllSettings(){
    return Object.assign(this.getDefaultData(), this.currentData);
  }

  getSetting(key){
    return this.getAllSettings()[key]
  }

  updateSetting(key, value){
    for(let i = 0; i < allApplicationSettings.length; i++){
      const setting = allApplicationSettings[i]
      if(setting.id === key){
        if(!setting.validate(value)){
          assert(false, '错误的设置值: ' + key);
        }
        this.currentData[key] = value;
        setting.apply(this.app, value)
        return this.writeAsync();
      }
    }
    assert(false, '未定义的设置: ' + key);
  }

  initialize(){
    return this.readAsync()
      .then(() => {
        const settings = this.getAllSettings();
        for(let i = 0; i < allApplicationSettings.length; i++){
          const handle = allApplicationSettings[i];
          handle.apply(this.app, settings[handle.id]);
        }
      })
      .then(() => this.writeAsync());
  }

  getInterfaceScaleId(){
    if(!this.currentData){
      return 'regular';
    }
    return this.getSetting('uiScale')
  }

  getInterfaceScaleValue(){
    const id = this.getInterfaceScaleId();
    for(let i = 0; i < uiScales.length; i++){
      if(uiScales[i].id === id){
        return uiScales[i].size
      }
    }

    logger.error('错误定义的uiScale id：', id);
    return;
  }
}